package com.tree.userservice.controller;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import com.tree.userservice.sao.UserFeignService;
import com.tree.userservice.sao.dto.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Field;
import java.util.List;

/**
 * @ClassName com.tree.userservice.controller
 * Description: <类功能描述>. <br>
 * <p>
 * <使用说明>
 * </p>
 * @Author tree
 * @Date 2019-07-06 19:16
 * @Version 1.0
 */
@Slf4j
@RestController
@RequestMapping("/ribbon")
public class ConsumerController implements ApplicationContextAware {
    private static final String INSTANCE_ID = "user-service";

    @Autowired
    private RestTemplate restTemplate;

    @Autowired(required = false)
    private List<RestTemplate> restTemplates;

    @Autowired
    private UserFeignService userFeignService;

    ApplicationContext applicationContext;

    @Value("${feignname.userservice.name}")
    private String userServiceName;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 获取instances
     * @return
     * @throws JsonProcessingException
     */
    @GetMapping("instances")
    public String getInstances() throws JsonProcessingException {
        //get service instance from eureka
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances(INSTANCE_ID);
        log.info("==> /index, host={},service-id={}", serviceInstances.get(0).getHost(),serviceInstances.get(0).getServiceId());
        return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(serviceInstances);
    }

    /**
     * 获取Ribbon Server
     * @return
     */
    @GetMapping("servers")
    public String getServers() {
        SpringClientFactory springClientFactory = applicationContext.getBean(SpringClientFactory.class);
        ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(userServiceName);
        List<Server> servers = loadBalancer.getReachableServers();
        for (Server server : servers) {
            //如果服务有设置zone，此处获取的可能并不是所有的实例
            System.out.println("---:" + server.getHostPort());
        }

        DynamicServerListLoadBalancer<DiscoveryEnabledServer> dynamicServerListLoadBalancer = (DynamicServerListLoadBalancer) loadBalancer;

        ServerList<DiscoveryEnabledServer> serverListImpl = dynamicServerListLoadBalancer.getServerListImpl();

        DomainExtractingServerList domainExtractingServerList1 = (DomainExtractingServerList) serverListImpl;

        try {
            Field field = domainExtractingServerList1.getClass().getDeclaredField("list");
            field.setAccessible(true);
            ServerList<DiscoveryEnabledServer> list = (ServerList<DiscoveryEnabledServer>) field.get(domainExtractingServerList1);

            for (DiscoveryEnabledServer server : list.getUpdatedListOfServers()) {
                //此处获取的是所有的实例
                System.out.println("%%%:" + server.getHostPort());
            }

            /*for(DiscoveryEnabledServer server:list.getInitialListOfServers()){
                System.out.println("+++:"+server.getHostPort());
            }*/
        } catch (Exception e) {
            e.printStackTrace();
        }
        return JSONUtil.toJsonPrettyStr(servers);
    }



    @GetMapping("/index")
    public String index(){
        return "index";
    }

    /**
     * ribbon resttemplate 接口
     * @return
     */
    @GetMapping("/hello-ribbon")
    public String helloConsumer(){
        return restTemplate.getForEntity("http://USER-SERVICE/user/index",String.class).getBody();
    }



    /**
     * 带参数feign
     * @return
     */
    @GetMapping("/hello-feign")
    public String hello(){

        StringBuilder sb = new StringBuilder(4048);
        //无参数
        String s  = userFeignService.index();
        sb.append(s).append("\n");

        User user =  userFeignService.hello(1,"tree",20);
        //带参数
        log.info("get user from User-Service, user={}", user);
        sb.append(JSON.toJSONString(user,true)).append("\n");

        user.setName("tree2");
        //使用requestBody
        s = userFeignService.hello2(user);

        sb.append(s);

        return sb.toString();

    }

    @GetMapping("/time")
    public String time(){
        return userFeignService.time();
    }

    @GetMapping("/longtime")
    public String longTime() throws InterruptedException {
//        Thread.sleep(3*1000);
        return userFeignService.longTime();
    }

    @GetMapping("/randomtime")
    public String randomtime() throws InterruptedException {
//        Thread.sleep(3*1000);
        return userFeignService.randomTime();
    }


}
